import { TrackOpTypes, TriggerOpTypes } from "./operations.js";

const targetMap = new WeakMap();
const ITERATE_KEY = Symbol("iterate");
let shouldTrack = true;
let activeEffect = undefined;
export function pauseTracking() {
  shouldTrack = false;
}

export function resumeTracking() {
  shouldTrack = true;
}

// 导出一个函数effect，参数为fn
export function effect(fn, options = {}) {
  const effectFn = () => {
    try {
      activeEffect = effectFn;
      return fn();
    } finally {
      activeEffect = null;
    }
  };
  if (!options.lazy) {
    effectFn(); // 如果不是 lazy，立即执行
  }
  return effectFn;
}
export function track(target, type, key) {
  if (!shouldTrack || !activeEffect) return;
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }
  if (type === TrackOpTypes.ITERATE) {
    key = ITERATE_KEY;
  }
  let typeMap = depsMap.get(key);
  if (!typeMap) {
    typeMap = new Map();
    depsMap.set(key, typeMap);
  }
  let depSet = typeMap.get(type);
  if (!depSet) {
    depSet = new Set();
    typeMap.set(type, depSet);
  }
  if (!depSet.has(activeEffect)) {
    depSet.add(activeEffect);
  }
  if (type == TrackOpTypes.ITERATE) {
    console.log(`%c依赖收集：${type}`, "color: #f00", key);
    return;
  }
  console.log(`%c依赖收集：${type}`, "color: #f00", key);
  console.log(depsMap);
}
export function trigger(target, type, key) {
  console.log(`%c派发更新：${type}`, "color: #666", key);
  const effectFns=getEffectFns(target,type,key)
  if(!effectFns) return;
  for(const effectFn of effectFns){
    effectFn()
  }
}

function getEffectFns(target, type, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;
  console.log('getEffectFns')
  const keys = [key];
  if (type === TriggerOpTypes.Add || type === TriggerOpTypes.Delete) {
    keys.push(ITERATE_KEY);
  }
  const effectFns = new Set();
  const triggerTypeMap={
    [TriggerOpTypes.Set]: [TriggerOpTypes.Get],
    [TriggerOpTypes.Add]: [TriggerOpTypes.Get, TriggerOpTypes.ITERATE,TriggerOpTypes.Has],
    [TriggerOpTypes.Delete]: [TriggerOpTypes.Get, TriggerOpTypes.ITERATE,TriggerOpTypes.Has],
  }

  for (const key of keys) {
    const typeMap = depsMap.get(key);
    if (!typeMap) {
      continue;
    }
    const triggerType = triggerTypeMap[type];
    for (const type of triggerType) {
      const depSet = typeMap.get(type);
      if(!depSet) continue;
      if (depSet) {
        depSet.forEach((effectFn) => {
          effectFns.add(effectFn);
        });
      }
    }
  }
  return effectFns;
}
